package com.fbt.energy.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.fbt.energy.entity.AO.AmmeterDataAO;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.*;

@Component
public class AmmeterDataS {


    // 授权码 后台获取
    private static String auth_code = "d443d58712378e27e08fd298179c9c24";
    // 随机字符串 后台获取
    private static String nonce = "0ToUQZogw5REP7CRS7ArB";
    // 测试用采集器号
    private static String debug_collector = "211003551932";
    // 测试用电表号
    private static String debug_meter = "211003551932";
    // 异步通知地址（服务如果部署在内网，在公网无法直接访问到，需要在路由器上配置端口映射，或者配置内网穿透工具来实现访问）
    private static String notify_url = "http://192.168.101.81:9290/notify";


    private static void 查询设备列表和当前状态() {
        // 查询设备列表和当前状态
        String url = "http://api1.tqdianbiao.com/Api/Meter";
        Map<String, Object> params = new HashMap<>();
        params.put("auth", auth_code);

        // Map<String, Object> 转成url参数
        String urlParams = getUrlParams(params);

        url = url + "?" + urlParams;

        String resp = HttpClientGet(url);

        simpleRequestPrint(url, resp);
    }


    private static void 查询电表当前状态数据() {
        // 查询电表当前状态数据
        String url = "http://api1.tqdianbiao.com/Api/EleMeterState";
        Map<String, Object> params = new HashMap<>();
        params.put("auth", auth_code);

        // Map<String, Object> 转成url参数
        String urlParams = getUrlParams(params);

        url = url + "?" + urlParams;

        String resp = HttpClientGet(url);

        simpleRequestPrint(url, resp);
    }

    // 查询当前小时用电量
    public static List<AmmeterDataAO> HistoricalData() {
        //     Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中小时 */
        //  calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1);
        /* MINUTE 指示一天中的某分 */
        // calendar.set(Calendar.MINUTE, (calendar.get(Calendar.MINUTE) - 2));


        Calendar calendarLastHour = Calendar.getInstance();
        //当前时间前十分钟
        calendarLastHour.set(Calendar.MINUTE, (calendarLastHour.get(Calendar.MINUTE) - 10));
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String LastHour = df.format(calendarLastHour.getTime());
     /*   System.out.println("10分钟 前 的时间：" + LastHour);

        System.out.println("当前 的时间：" + df.format(new Date()));
*/
        Calendar calendarNextHour = Calendar.getInstance();
        //当前时间后半个小时
        calendarNextHour.set(Calendar.MINUTE, calendarNextHour.get(Calendar.MINUTE) + 30);
        String NextHour = df.format(calendarNextHour.getTime());
/*
        System.out.println("30分钟 后 的时间：" + NextHour);
*/
        String url = "http://api1.tqdianbiao.com/Api/DataRequest";
        Map<String, Object> params = new HashMap<>();
        params.put("auth", auth_code);
        params.put("type", "json");
        params.put("functionids", "3");
        params.put("start_time", LastHour);
        params.put("end_time", NextHour);
        params.put("offset", 0);
        params.put("limit", 100);

        // Map<String, Object> 转成url参数
        String urlParams = getUrlParams(params);

        url = url + "?" + urlParams;

        String resp = HttpClientGet(url);

        simpleRequestPrint(url, resp);
        JSONObject jsonObject = JSON.parseObject(resp);
        Integer status = jsonObject.getInteger("status");

        System.out.println("状态码为" + status);
        List<AmmeterDataAO> dataAOS = new ArrayList<>();

        if (status == 1) {
            JSONArray jsonArray = jsonObject.getJSONArray("data");
            List<AmmeterDataAO> ammeterDataAOList = JSON.parseObject(jsonArray.toJSONString(), new TypeReference<List<AmmeterDataAO>>() {
            });

            for (AmmeterDataAO ammeterAO : ammeterDataAOList) {
                AmmeterDataAO returnAmmeterAo = new AmmeterDataAO();
                BeanUtils.copyProperties(ammeterAO, returnAmmeterAo);
                dataAOS.add(returnAmmeterAo);
            }


        }
        return dataAOS;
    }

    //查询前一个小时的用电量
    public static List<AmmeterDataAO> LastHourDate() {

        Calendar calendarLastHour = Calendar.getInstance();
        //前一个小时
        calendarLastHour.set(Calendar.HOUR_OF_DAY, calendarLastHour.get(Calendar.HOUR_OF_DAY) - 1);
        //当前时间前十分钟
        calendarLastHour.set(Calendar.MINUTE, (calendarLastHour.get(Calendar.MINUTE) - 10));
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String LastHour = df.format(calendarLastHour.getTime());
      /*  System.out.println("一个小时10分钟 前 的时间：" + LastHour);

        System.out.println("当前 的时间：     " + df.format(new Date()));
*/

        Calendar calendarNextHour = Calendar.getInstance();
        //前一个小时
        calendarNextHour.set(Calendar.HOUR_OF_DAY, calendarNextHour.get(Calendar.HOUR_OF_DAY) - 1);
        //当前时间后半个小时
        calendarNextHour.set(Calendar.MINUTE, calendarNextHour.get(Calendar.MINUTE) + 30);
        String NextHour = df.format(calendarNextHour.getTime());
/*

        System.out.println("30分钟 前 的时间：" + NextHour);

*/


        String url = "http://api1.tqdianbiao.com/Api/DataRequest";
        Map<String, Object> params = new HashMap<>();
        params.put("auth", auth_code);
        params.put("type", "json");
        params.put("functionids", "3");
        params.put("start_time", LastHour);
        params.put("end_time", NextHour);

        params.put("offset", 0);
        params.put("limit", 100);

        // Map<String, Object> 转成url参数
        String urlParams = getUrlParams(params);

        url = url + "?" + urlParams;

        String resp = HttpClientGet(url);

        simpleRequestPrint(url, resp);
        JSONObject jsonObject = JSON.parseObject(resp);
        Integer status = jsonObject.getInteger("status");

        System.out.println("状态码为" + status);
        List<AmmeterDataAO> dataLestAOS = new ArrayList<>();

        if (status == 1) {
            JSONArray jsonArray = jsonObject.getJSONArray("data");
            List<AmmeterDataAO> ammeterDataAOList = JSON.parseObject(jsonArray.toJSONString(), new TypeReference<List<AmmeterDataAO>>() {
            });

            for (AmmeterDataAO ammeterAO : ammeterDataAOList) {
                AmmeterDataAO returnAmmeterAo = new AmmeterDataAO();
                BeanUtils.copyProperties(ammeterAO, returnAmmeterAo);
                dataLestAOS.add(returnAmmeterAo);
            }


        }
        return dataLestAOS;
    }


    private static void simpleRequestPrint(String url, String resp) {
        String name = Thread.currentThread().getStackTrace()[2].getMethodName();
        System.out.println(name);

        System.out.println("请求参数：" + url);
        System.out.println("返回数据：" + resp);
    }

    private static String HttpClientGet(String url) {
        try {
            CloseableHttpClient client = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse Response = client.execute(httpGet);
            HttpEntity entity = Response.getEntity();
            String resp = EntityUtils.toString(entity, "UTF-8");
            Response.close();
            return resp;
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return "";
        }
    }

    private static String getUrlParams(Map<String, Object> map) {
        if (map == null || map.size() == 0) {
            return "";
        }
        List<String> list = new ArrayList<>();
        map.forEach((key, value) -> {
            try {
                list.add(key + "=" + URLEncoder.encode(value.toString(), "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        });
        return String.join("&", list);
    }


    private static void 电表拉闸() {
        String url = "http://api2.tqdianbiao.com/Api_v2/ele_control";

        // 请求内容，调用接口所需要的数据（电表拉闸）
        List<Map<String, Object>> req = new ArrayList<>();
        Map<String, Object> item = new HashMap<>();

        item.put("opr_id", generateOperateId());
        item.put("time_out", 0);
        item.put("must_online", true);
        item.put("retry_times", 1);
        item.put("cid", "19020618114");
        item.put("address", "000066660942");
        item.put("type", 10);
        req.add(item);

        String request_content = JSON.toJSONString(req);
        testApiAsync(url, request_content);

    }

    private static void 电表合闸() {
        String url = "http://api2.tqdianbiao.com/Api_v2/ele_control";

        // 请求内容，调用接口所需要的数据（电表合闸）
        List<Map<String, Object>> req = new ArrayList<>();
        Map<String, Object> item = new HashMap<>();

        item.put("opr_id", generateOperateId());
        item.put("time_out", 0);
        item.put("must_online", true);
        item.put("retry_times", 1);
        item.put("cid", "19020618114");
        item.put("address", "000066660942");
        item.put("type", 11);
        req.add(item);

        String request_content = JSON.toJSONString(req);
        testApiAsync(url, request_content);

    }
    private static void 抄电表数据() {
        String url = "http://api2.tqdianbiao.com/Api_v2/ele_read";

        // 请求内容，调用接口所需要的数据（抄电表数据）
        List<Map<String, Object>> req = new ArrayList<>();
        Map<String, Object> item = new HashMap<>();
        item.put("opr_id", generateOperateId());
        item.put("time_out", 0);
        item.put("must_online", true);
        item.put("retry_times", 1);
        item.put("address", "211003551932");
        item.put("type", 3);
        item.put("cid", "211003551932");
        req.add(item);

        String request_content = JSON.toJSONString(req);

        testApiAsync(url, request_content);

    }


    private static String generateOperateId() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }


    private static void 操作状态查询() {
        String url = "http://api2.tqdianbiao.com/Api_v2/request/status";
        // 请求内容，调用接口所需要的数据(操作状态查询)
        List<Map<String, String>> req = new ArrayList<>();
        Map<String, String> item = new HashMap<>();
        item.put("opr_id", "123456");
        req.add(item);
        String request_content = JSON.toJSONString(req);

        testApi(url, request_content);
    }

    private static void 取消操作() {
        String url = "http://api2.tqdianbiao.com/Api_v2/request/cancel";
        // 请求内容，调用接口所需要的数据(取消操作)
        List<Map<String, String>> req = new ArrayList<>();
        Map<String, String> item = new HashMap<>();
        item.put("opr_id", "123456");
        req.add(item);
        String request_content = JSON.toJSONString(req);

        testApi(url, request_content);
    }

    private static void 查询全部采集器() {
        String url = "http://api2.tqdianbiao.com/Api_v2/collector/query";
        // 请求内容，调用接口所需要的数据（查询所有采集器信息）
        String request_content = "[]";

        testApi(url, request_content);
    }

    private static void 查询N个采集器() {
        String url = "http://api2.tqdianbiao.com/Api_v2/collector/query";
        // 请求内容，调用接口所需要的数据(查询指定的采集器信息)
        List<Map<String, String>> req = new ArrayList<>();
        Map<String, String> item = new HashMap<>();
        item.put("cid", "100000000101");
        req.add(item);
        item = new HashMap<>();
        item.put("cid", "10000000101");
        req.add(item);
        item = new HashMap<>();
        item.put("cid", "1000000101");      // 采集器号不符合规范
        req.add(item);
        item = new HashMap<>();
        item.put("cid", "50000000101");     // 不存在的采集器
        req.add(item);
        String request_content = JSON.toJSONString(req);

        testApi(url, request_content);
    }

    private static void testApi(String url, String request_content) {
        String name = Thread.currentThread().getStackTrace()[2].getMethodName();
        System.out.println(name);

        String response = request(url, request_content);
        printResponse(response);
    }

    private static void testApiAsync(String url, String request_content) {
        String name = Thread.currentThread().getStackTrace()[2].getMethodName();
        System.out.println(name);

        String response = requestAsync(url, request_content);
        /* System.out.println("respo  ns  e "+response);*/
        printResponse(response);
    }

    // 打印响应内容
    private static void printResponse(String response) {
        JSONObject jsonObject = JSON.parseObject(response);

        String status = jsonObject.getString("status");
        if (!"SUCCESS".equals(status)) {
            System.out.println(jsonObject.getString("error_msg"));
        } else {
            String response_content = jsonObject.getString("response_content");
            System.out.println("response_content: " + response_content);
            JSONArray contentArray = JSON.parseArray(response_content);
            System.out.println("contentA rra   y" + contentArray);

            int index = 1;
            System.out.println("返回结果：");
            for (int i = 0; i < contentArray.size(); ++i) {
                System.out.println("[" + index++ + "]");
                JSONObject contentObject = contentArray.getJSONObject(i);
                Set<String> keySet = contentObject.keySet();
                for (String key : keySet) {
                    System.out.println(key + ": " + contentObject.get(key));
                }

            }
        }
    }

    // 请求接口
    private static String request(String url, String request_content) {
        // 时间戳
        String timestamp = String.valueOf(new Date().getTime() / 1000);

        // 用于签名的内容
        Map<String, String> data = new HashMap<>();
        data.put("timestamp", timestamp);
        data.put("auth_code", auth_code);
        data.put("request_content", request_content);

        // 获取签名
        String sign = getSign(data);

        data.put("sign", sign);

        try {
            return sendHttpRequest(url, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    // 请求接口
    private static String requestAsync(String url, String request_content) {
        // 时间戳
        String timestamp = String.valueOf(new Date().getTime() / 1000);

        // 用于签名的内容
        Map<String, String> data = new HashMap<>();
        data.put("timestamp", timestamp);
        data.put("auth_code", auth_code);
        data.put("request_content", request_content);
        data.put("notify_url", notify_url);

        // 获取签名
        String sign = getSign(data);

        data.put("sign", sign);

        try {
            return sendHttpRequest(url, data);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    // 生成签名字符串
    private static String getSign(Map<String, String> data) {
        // 获取关键字列表
        List<String> keys = new ArrayList<>(data.keySet());
        // 关键字列表排序
        keys.sort(Comparator.naturalOrder());
        StringBuilder sb = new StringBuilder();
        for (String key : keys) {
            // 取各个字段内容拼接字符串
            sb.append(data.get(key));
        }
        // 加上双方约定随机字符串
        String txt = sb.toString() + nonce;

        // 计算哈希值
        return getMD5(txt);
    }

    // md5加密
    private static String getMD5(String password) {
        MessageDigest md5 = null;
        try {
            md5 = MessageDigest.getInstance("MD5");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        byte[] byteArray = password.getBytes(StandardCharsets.UTF_8);

        byte[] md5Bytes = md5.digest(byteArray);
        StringBuilder hexValue = new StringBuilder();
        for (byte md5Byte : md5Bytes) {
            int val = ((int) md5Byte) & 0xff;
            if (val < 16) {
                hexValue.append("0");
            }

            hexValue.append(Integer.toHexString(val));
        }
        return hexValue.toString();
    }

    // 发送http请求
    private static String sendHttpRequest(String url, Map<String, String> bodyMap) throws Exception {
        System.out.println("请求地址：" + url);
        System.out.println("发送参数：" + bodyMap.toString());
        HttpClient client = HttpClientBuilder.create().build();
        HttpPost postRequest = new HttpPost(url);

        List<NameValuePair> nvps = new ArrayList<>();

        for (String key : bodyMap.keySet()) {
            nvps.add(new BasicNameValuePair(key, bodyMap.get(key)));
        }
        postRequest.setEntity(new UrlEncodedFormEntity(nvps, "utf-8"));


        int retry = 3;
        HttpResponse execute = null;
        while (retry-- > 0) {
            try {
                execute = client.execute(postRequest);
                break;
            } catch (Exception e) {
                Thread.sleep(5000);
            }
        }
        if (execute == null) {
            throw new Exception("接口请求失败");
        }
        String resp = EntityUtils.toString(execute.getEntity(), "UTF-8");
        System.out.println("接口返回：" + resp);
        return resp;
    }

}